using System;
using EnvDTE;
using EnvDTE80;
using VSSDKAssist.Assets.Helpers;
using VSSDKAssist.Assets.ValueProviders.Base;

namespace VSSDKAssist.Recipes.ConfigureVSPlk
{
	/// <summary>
	/// Value provider for the ProvideLoadKey attribute
	/// </summary>
	public class ProvideLoadKeyAttributeValueProvider : ValueProviderBase
	{
		#region Constants
		private const string CodeClassArgument = "CodeClassArgument";
		private const string AttributeArgument = "AttributeArgument";
		#endregion

		#region Fields
		private string codeClassArgument;
		private string attributeArgument;
		#endregion

		/// <summary>
		/// Contains code that will be called when recipe execution begins. This is the first method in the lifecycle.
		/// </summary>
		/// <param name="currentValue">An <see cref="T:System.Object"/> that contains the current value of the argument.</param>
		/// <param name="newValue">When this method returns, contains an <see cref="T:System.Object"/> that contains
		/// the new value of the argument, if the returned value
		/// of the method is <see langword="true"/>. Otherwise, it is ignored.</param>
		/// <returns>
		/// 	<see langword="true"/> if the argument value should be replaced with
		/// the value in <paramref name="newValue"/>; otherwise, <see langword="false"/>.
		/// </returns>
		/// <remarks>By default, always returns <see langword="false"/>, unless overriden by a derived class.</remarks>
		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1305:SpecifyIFormatProvider", MessageId = "System.Int32.ToString")]
		public override bool OnBeginRecipe(object currentValue, out object newValue)
		{
			const string ProvideLoadKey = "ProvideLoadKey";

			newValue = null;

			if((currentValue == null) && (this.ExecutionStage != Stage.OnBeforeActions))
			{
				CodeClass codeClassArgumentValue = DictionaryService.GetValue(codeClassArgument) as CodeClass;

				if(codeClassArgumentValue != null)
				{
					CodeAttribute attribute = FileCodeModelHelper.GetAttribute(codeClassArgumentValue, ProvideLoadKey);

					if(attribute != null)
					{
						if(!string.IsNullOrEmpty(this.attributeArgument))
						{
							CodeAttribute2 attribute2 = (EnvDTE80.CodeAttribute2)attribute;

							if(this.attributeArgument.Equals("MinimumEdition", StringComparison.OrdinalIgnoreCase))
							{
								newValue = SanitizeValue((attribute2.Arguments.Item(1) as CodeAttributeArgument).Value);
								return true;
							}
							else if(this.attributeArgument.Equals("ProductVersion", StringComparison.OrdinalIgnoreCase))
							{
								newValue = SanitizeValue((attribute2.Arguments.Item(2) as CodeAttributeArgument).Value);
								return true;
							}
							else if(this.attributeArgument.Equals("ProductName", StringComparison.OrdinalIgnoreCase))
							{
								newValue = SanitizeValue((attribute2.Arguments.Item(3) as CodeAttributeArgument).Value);
								return true;
							}
							else if(this.attributeArgument.Equals("CompanyName", StringComparison.OrdinalIgnoreCase))
							{
								newValue = SanitizeValue((attribute2.Arguments.Item(4) as CodeAttributeArgument).Value);
								return true;
							}
							else if(this.attributeArgument.Equals("ResourceId", StringComparison.OrdinalIgnoreCase))
							{
								newValue = SanitizeValue((attribute2.Arguments.Item(5) as CodeAttributeArgument).Value);
								return true;
							}
						}
					}
					else
					{
						if(!string.IsNullOrEmpty(this.attributeArgument))
						{
							if(this.attributeArgument.Equals("ResourceId", StringComparison.OrdinalIgnoreCase))
							{
								newValue = CommonHelper.GetRandomNumber().ToString();
								return true;
							}
						}
					}
				}
			}

			return false;
		}

		/// <summary>
		/// Called when [configure].
		/// </summary>
		/// <param name="attributes">The attributes.</param>
		protected override void OnConfigure(System.Collections.Specialized.StringDictionary attributes)
		{
			if(attributes == null)
				throw new ArgumentNullException("attributes");

			if(attributes.ContainsKey(CodeClassArgument))
			{
				codeClassArgument = attributes[CodeClassArgument];
			}

			if(attributes.ContainsKey(AttributeArgument))
			{
				attributeArgument = attributes[AttributeArgument];
			}
		}

		#region Private Implementation
		private static string SanitizeValue(string attValue)
		{
			string formattedValue = attValue;
			formattedValue = attValue.Replace("@\"", "");
			formattedValue = formattedValue.Replace("\"", "");
			formattedValue = formattedValue.Replace("\\\\", "\\");

			return formattedValue;
		}
		#endregion
	}
}